package com.kakarote.admin.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.kakarote.admin.entity.BO.AdminRouterSaveBO;
import com.kakarote.admin.entity.BO.AdminRouterSaveRequestBO;
import com.kakarote.admin.entity.BO.AdminRouterTitleUpdateBO;
import com.kakarote.admin.mapper.AdminRouterMapper;
import com.kakarote.admin.service.IAdminRouterService;
import com.kakarote.core.feign.admin.entity.AdminRouter;
import com.kakarote.core.servlet.BaseServiceImpl;
import com.kakarote.core.utils.BaseUtil;
import com.kakarote.core.utils.UserUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 全局路由配置表 服务实现类
 *
 * @author zjj
 * @since 2022-08-08
 */
@Service
public class AdminRouterServiceImpl extends BaseServiceImpl<AdminRouterMapper, AdminRouter> implements IAdminRouterService {


    @Override
    @Transactional(rollbackFor = Exception.class)
    public AdminRouter saveRouter(AdminRouterSaveBO saveBO) {
        if (ObjectUtil.isNotNull(saveBO.getId())) {
            removeById(saveBO.getId());
        }
        AdminRouter router = BeanUtil.copyProperties(saveBO, AdminRouter.class);
        if (ObjectUtil.isNull(saveBO.getRouterId())) {
            router.setRouterId(BaseUtil.getNextId());
        }
        router.setCreateTime(LocalDateTime.now());
        router.setCreateUserId(UserUtil.getUserId());
        save(router);
        return router;
    }

    @Override
    public void updateTitleByModuleId(AdminRouterTitleUpdateBO updateBO) {
        lambdaUpdate()
                .set(AdminRouter::getTitle, updateBO.getTitle())
                .set(AdminRouter::getIcon, updateBO.getIcon())
                .eq(AdminRouter::getSourceModuleId, updateBO.getSourceModuleId())
                .update();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchSaveRouter(AdminRouterSaveRequestBO requestBO) {
        lambdaUpdate().eq(AdminRouter::getApplicationId, requestBO.getApplicationId()).remove();
        List<AdminRouterSaveBO> routerList = requestBO.getRouterList();
        if (CollUtil.isNotEmpty(routerList)) {
            Map<Long, Long> tempIdToIdMap = new HashMap<>();
            List<AdminRouter> routers = routerList.stream().map(r -> {
                AdminRouter router = BeanUtil.copyProperties(r, AdminRouter.class);
                Long routerId = BaseUtil.getNextId();
                tempIdToIdMap.put(router.getRouterId(), routerId);
                router.setId(null);
                router.setRouterId(routerId);
                router.setApplicationId(requestBO.getApplicationId());
                router.setCreateTime(LocalDateTime.now());
                router.setCreateUserId(UserUtil.getUserId());
                return router;
            }).collect(Collectors.toList());
            for (AdminRouter router : routers) {
                if (ObjectUtil.isNotNull(router.getParentId())) {
                    router.setParentId(MapUtil.getLong(tempIdToIdMap, router.getParentId()));
                } else {
                    router.setParentId(0L);
                }

            }
            saveBatch(routers);
        }
    }

    @Override
    public void deleteAll(Long applicationId) {
        lambdaUpdate().eq(AdminRouter::getApplicationId, applicationId).remove();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteRouter(Long id) {
        AdminRouter router = getById(id);
        removeById(id);
        lambdaUpdate().eq(AdminRouter::getParentId, router.getRouterId()).remove();
    }

    @Override
    public List<AdminRouter> listRouter(Long applicationId) {
        return lambdaQuery()
                .eq(AdminRouter::getApplicationId, applicationId)
                .orderByAsc(AdminRouter::getSort)
                .list();
    }
}
